Skip to content

Fix: 결제 승인 시각을 Toss 승인 시각으로 기록하도록 수정 - #416

Merged
soyeon1806 merged 1 commit into
devfrom
fix/payment-authoritative-approved-at
Jul 14, 2026
Merged

Fix: 결제 승인 시각을 Toss 승인 시각으로 기록하도록 수정#416
soyeon1806 merged 1 commit into
devfrom
fix/payment-authoritative-approved-at

Conversation

@soyeon1806

@soyeon1806 soyeon1806 commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

✅ PR 설명

결제 완결 시 approvedAt을 서버의 LocalDateTime.now()로 기록하고 있어, PG(Toss)가 확정한 실제 승인 시각과 어긋날 수 있었습니다.
특히 reconciliation 배치로 완결되는 경우 실제 승인과 우리 기록 사이에 수십 분 오차가 발생하며, 이 값은 환불 7일 기한 판정 기준이기도 합니다.
따라서 결제 원장의 승인 시각을 Toss 응답의 approvedAt을 source of truth로 기록하도록 수정했습니다.

🏗 작업 내용

  • completePayment에 approvedAt 파라미터 추가
  • Toss 확정 승인 시각을 원장에 기록, 값이 없으면 서버 시각으로 대체
  • verifyPayment에서Toss confirm 응답에서 approvedAt 추출해 전달하도록 수정
  • TossPaymentClient.parseTossDateTime 추가로 ISO-8601 오프셋 시각 파싱 로직 일원화 및 findPaymentByOrderId가 approvedAt 파싱
  • TossPaymentInfo에 approvedAt 추가
  • verifyPayment의 예외 처리에 catch (BusinessException) throw e를 추가하여 내부 도메인 예외가 PAYMENT_VERIFICATION_FAILED로 뭉개지지 않도록 정리

📸 테스트 결과 (선택)

  • PaymentServiceTest 23/23
  • PaymentReconciliationServiceTest 6/6
  • TossPaymentClientTest 7/7

🔗 관련 이슈 (선택)

관련된 Issue가 있다면 #이슈번호 형식으로 작성해주세요.

🚨 참고 사항 (선택)

  • canceledAt은 여전히 서버 시각입니다.
  • Toss 취소 시각을 쓰려면 cancelPayment 클라이언트가 boolean 대신 취소 응답을 반환하도록 바꿔야 해서 별도 스코프로 남겼습니다.
  • Toss approvedAt은 타임존 오프셋 포함(+09:00)이며 OffsetDateTime으로 파싱 후 LocalDateTime으로 변환합니다.

@soyeon1806 soyeon1806 self-assigned this Jul 14, 2026
@soyeon1806
soyeon1806 merged commit a99c3ed into dev Jul 14, 2026
2 checks passed
@soyeon1806
soyeon1806 deleted the fix/payment-authoritative-approved-at branch July 14, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant